//-----------------------------------------------------------------------------
//	File: mgui_menu.c
//	Author: xialing
//		menu of mgui
//-----------------------------------------------------------------------------

#include "mgui_menu.h"

static Menu_TypeDef *menu;

//-----------------------------------------------------------------------------
//	mgui_menu_putc - mgui put a character using menu font
//		@c: character
//-----------------------------------------------------------------------------
static void mgui_menu_putc(char c, uint16_t x, uint16_t y)
{
	uint8_t i, j;
	uint8_t *p;
	uint16_t k;

	p = menu->conf->font->dat + (c - 0x20) * menu->conf->font->b;
	for (j=0,k=0; j<menu->conf->font->h; j++) {
		for (i=0; i<menu->conf->font->w; i++,k++) {
			if (p[k >> 3] & (1 << (k & 7))) {
				mgui_draw_pixel(x + i, y + j, 1 ^ mgui_conf->invc);
			} else {
				mgui_draw_pixel(x + i, y + j, 0 ^ mgui_conf->invc);
			}
		}
	}
}

//-----------------------------------------------------------------------------
//	mgui_menu_puts - mgui put string for menu
//		@s: string
//		@row: NO.x of menu row
//-----------------------------------------------------------------------------
static void mgui_menu_puts(char *s, uint8_t row)
{
	uint16_t x = menu->conf->menu_x1 + (menu->conf->gapx << 1);
	uint16_t y = menu->conf->menu_y1 + (menu->conf->gapy << 1)
		+ (menu->conf->font->h * row);
	uint8_t i;

	for (i=0; i<menu->col; i++) {
		if (*s == '\0') {
			mgui_menu_putc(' ', x, y);
		} else {
			mgui_menu_putc(*s++, x, y);
		}
		x += menu->conf->font->w;
	}
}

//-----------------------------------------------------------------------------
//	mgui_menu_puts_inv - mgui put string inverse
//		@s: string
//		@row: NO.x of menu row
//-----------------------------------------------------------------------------
static void mgui_menu_puts_inv(char *s, uint8_t row)
{
	uint16_t x = menu->conf->menu_x1 + (menu->conf->gapx << 1);
	uint16_t y = menu->conf->menu_y1 + (menu->conf->gapy << 1)
		+ (menu->conf->font->h * row);
	uint8_t i;

	mgui_conf->invc ^= 1;
	for (i=0; i<menu->col; i++) {
		if (*s == '\0') {
			mgui_menu_putc(' ', x, y);
		} else {
			mgui_menu_putc(*s++, x, y);
		}
		x += menu->conf->font->w;
	}
	mgui_conf->invc ^= 1;
}

//-----------------------------------------------------------------------------
//	mgui_menu_puts_clr - mgui put string space
//		@row: NO.x of menu row
//-----------------------------------------------------------------------------
static void mgui_menu_puts_clr(uint8_t row)
{
	uint16_t x = menu->conf->menu_x1 + (menu->conf->gapx << 1);
	uint16_t y = menu->conf->menu_y1 + (menu->conf->gapy << 1)
		+ (menu->conf->font->h * row);
	uint8_t i;

	for (i=0; i<menu->col; i++) {
		mgui_menu_putc(' ', x, y);
		x += menu->conf->font->w;
	}
}

//-----------------------------------------------------------------------------
//	mgui_menu_init - init menu
//		@m: menu
//-----------------------------------------------------------------------------
void mgui_menu_init(Menu_TypeDef *m, void (*f)(MenuMesg_TypeDef))
{
	m->col = (m->conf->menu_x2 - m->conf->menu_x1 - (m->conf->gapx << 2) + 1)
		/ m->conf->font->w;
	m->row = (m->conf->menu_y2 - m->conf->menu_y1 - (m->conf->gapy << 2) + 1)
		/ m->conf->font->h;
	m->func = f;

	menu = m;
}

//-----------------------------------------------------------------------------
//	menu_disp - display the menu
//-----------------------------------------------------------------------------
void mgui_menu_disp(void)
{
	uint8_t i;
	MenuMesg_TypeDef msg;

	mgui_draw_rect(menu->conf->menu_x1, menu->conf->menu_y1,
		menu->conf->menu_x2, menu->conf->menu_y2, !menu->sel ^ mgui_conf->invc);
	mgui_draw_rect(menu->conf->item_x1, menu->conf->item_y1,
		menu->conf->item_x2, menu->conf->item_y2, menu->sel ^ mgui_conf->invc);

	mgui_menu_puts(menu->list->name, 0);
	for (i=menu->top; i<(menu->top + menu->row - 1); i++) {
		if (i == menu->item) {
			mgui_menu_puts_inv(menu->list->array[i].name, i - menu->top + 1);
		} else {
			if (i < menu->list->num) {
				mgui_menu_puts(menu->list->array[i].name, i - menu->top + 1);
			} else {
				mgui_menu_puts_clr(i - menu->top + 1);
			}
		}
	}

 	msg.id = menu->list->array[menu->item].id;
	msg.opt = FUNC_DISP;
	menu->func(msg);
}

//-----------------------------------------------------------------------------
//	mgui_menu_enter - enter the subordinate menu or execute a function
//-----------------------------------------------------------------------------
void mgui_menu_enter(void)
{
	MenuMesg_TypeDef msg;

	if (menu->list->array[menu->item].child == NULL) {
 		msg.id = menu->list->array[menu->item].id;
		msg.opt = FUNC_ENTER;
		menu->func(msg);
	} else {
		menu->list = menu->list->array[menu->item].child;
		menu->top_l = menu->top;
		menu->item_l = menu->item;
		menu->top = 0;
		menu->item = 0;
	}
}

//-----------------------------------------------------------------------------
//	mgui_menu_up - go to the up item of menu
//-----------------------------------------------------------------------------
void mgui_menu_up(void)
{
	MenuMesg_TypeDef msg;

	if (menu->sel) {
 		msg.id = menu->list->array[menu->item].id;
		msg.opt = FUNC_UP;
		menu->func(msg);
	} else if (menu->item > 0) {
		menu->item--;
		if (menu->top > menu->item) {
			menu->top--;
		}
	}
}

//-----------------------------------------------------------------------------
//	mgui_menu_down - go to the down item of menu
//-----------------------------------------------------------------------------
void mgui_menu_down(void)
{
	MenuMesg_TypeDef msg;

	if (menu->sel) {
 		msg.id = menu->list->array[menu->item].id;
		msg.opt = FUNC_DOWN;
		menu->func(msg);
	} else if (menu->item < (menu->list->num - 1)) {
		menu->item++;
		if ((menu->item - menu->top) == (menu->row - 1)) {
			menu->top++;
		}
	}
}

//-----------------------------------------------------------------------------
//	mgui_menu_back - back to the parent menu
//-----------------------------------------------------------------------------
void mgui_menu_back(void)
{
	if (menu->sel) {
 		menu->sel = 0;
	} else if (menu->list->parent != NULL) {
		menu->list = menu->list->parent;
		menu->top = menu->top_l;
		menu->item = menu->item_l;
	}
}

//-----------------------------------------------------------------------------
//	mgui_menu_back - back to the parent menu
//		@sw: 0=menu, 1=item, 2=inv
//-----------------------------------------------------------------------------
void mgui_menu_sel(uint8_t sw)
{
	switch (sw) {
		case 0: menu->sel = 0; break;
		case 1: menu->sel = 1; break;
		case 2: menu->sel ^= 1; break;
	}
}
